#include "MemDataPage.hpp"

struct MemDataPage *CreateDataPage( void *subject_to_object , size_t dataunit_size )
{
	struct MemDataPage	*datapage = NULL ;
	size_t			dataunit_prealloc_count ;
	size_t			page_size ;
	
	dataunit_prealloc_count = sizeof0(struct MemDataPage,dataunit_used_bitmap) * 8 ;
	page_size = sizeof(struct MemDataPage) + dataunit_size * dataunit_prealloc_count ;
	datapage = (struct MemDataPage *)malloc( page_size ) ;
	if( datapage == NULL )
		return NULL;
	memset( datapage , 0x00 , page_size );
	
	datapage->subject_to_object = subject_to_object ;
	datapage->dataunit_size = dataunit_size ;
	datapage->dataunit_prealloc_count = dataunit_prealloc_count ;
	datapage->dataunit_used_count = 0 ;
	datapage->dataunit_used_bitmap = 0 ;
	
	return datapage;
}

void DestroyDataPage( struct MemDataPage *datapage )
{
	free( datapage );
	
	return;
}

size_t GetDataUnitSize( struct MemDataPage *datapage )
{
	return datapage->dataunit_size;
}

size_t GetPreAllocCount( struct MemDataPage *datapage )
{
	return datapage->dataunit_prealloc_count;
}

size_t GetUsedCount( struct MemDataPage *datapage )
{
	return datapage->dataunit_prealloc_count;
}

bool IsEmpty( struct MemDataPage *datapage )
{
	return (datapage->dataunit_used_count==0);
}

bool IsFull( struct MemDataPage *datapage )
{
	return (datapage->dataunit_used_count==datapage->dataunit_prealloc_count);
}

char *GetUnusedDataUnit( struct MemDataPage *datapage )
{
	uint64_t	dataunit_no ;
	char		*dataunit = NULL ;
	uint64_t	setbit_used_bitmap ;
	
	if( IsFull(datapage) == true )
		return NULL;
	
	dataunit_no = __builtin_clzl( ~(datapage->dataunit_used_bitmap) ) ;
	dataunit = datapage->dataunit_array_base + datapage->dataunit_size * dataunit_no ;
	setbit_used_bitmap = 1 ;
	setbit_used_bitmap = ( setbit_used_bitmap << (sizeof(datapage->dataunit_used_bitmap)*8-1-dataunit_no) ) ;
#if MDB_TRACE
	cout << "dataunit_no[" << dataunit_no << "] dataunit[" << static_cast<void*>(dataunit) << "] setbit_used_bitmap[" <<hex << setbit_used_bitmap << "] datapage->dataunit_used_bitmap[" << datapage->dataunit_used_bitmap << "]" << endl ;
#endif
	datapage->dataunit_used_bitmap |= setbit_used_bitmap ;
#if MDB_TRACE
	cout << "datapage->dataunit_used_bitmap[" <<hex << datapage->dataunit_used_bitmap << "]" << endl ;
#endif
	datapage->dataunit_used_count++;
#if MDB_TRACE
	cout << "datapage->dataunit_used_count[" << datapage->dataunit_used_count << "]" << endl ;
#endif
	
	return dataunit;
}

void SetDataUnitUnused( struct MemDataPage *datapage , char *dataunit )
{
	size_t		dataunit_no ;
	uint64_t	unsetbit_used_bitmap ;
	
	dataunit_no = ( dataunit - datapage->dataunit_array_base ) / datapage->dataunit_size ;
	unsetbit_used_bitmap = ( 1 << (sizeof(datapage->dataunit_used_bitmap)*8-1-dataunit_no) ) ;
	datapage->dataunit_used_bitmap &= ~unsetbit_used_bitmap ;
	datapage->dataunit_used_count--;
	
	return;
}

